// permission 文件: 主要用来页面跳转时进行权限校验的, 可以在里面配置 路由守卫 钩子函数等
// 切换路由时就会执行 permission文件
// 具体封装的函数有:
// 1. request.js 封装axios, 里面书写拦截器
// 2. auth.js 封装的是 操作 cookie 的几个函数
// 3. get-page-title.js 封装的是操作页面标题的函数
// 4. validate 封装的是一些数据校验的函数
// 导入路由对象
import router, { asyncRoutes } from '@/router'
import store from '@/store'
// 虚拟进度条: 开始进度条NProgress.start()  结束进度条NProgress.done()
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css'
import getPageTitle from '@/utils/get-page-title'

// 登录页面 不需要登录就可以访问，
// 白名单 ： 项目里面 不需要token，不需要登录既可以看见的页面  注册页  登录页面  404 等
const whiteList = ['/login', '/404']
// 判断一个元素 在不在 数组里面
//  arr.includes(xxx)    arr.indexOf(xxx) === -1

// 路由守卫， 2个函数---钩子函数， 在进入页面开始的时候自动执行
router.beforeEach(async(to, from, next) => {
  // 动态修改 title, 实现点击对应菜单标题, 切换网页的 标题
  // document.title = to.meta.title
  document.title = getPageTitle(to.meta.title)

  NProgress.start() // 开始进度条NProgress: 在路由守卫开启前, 开启进度条
  const token = store.state.user.token
  // console.log(token)
  // next()
  // 路由跳转判断， 先看有没有登录 （就是看有没有token值）
  if (token) {
    // if (to.path === '/login') {
    if (whiteList.includes(to.path)) {
      // 如果已经登录成功，还要去登录页面，用户体验就不好，应该直接给他跳转到首页
      next('/')
      NProgress.done()
    } else {
      // 当有token(用户已经登录), 并且要去的页面不是 login 时, 就发送请求获取用户信息数据
      // 这里必须要加 await 因为不加的话, 这个代码就不会等请求返回的结果, 直接走了 next, 代码逻辑就不对
      // 问题： 当用户已经登录后， 每次访问新的路由， 都会重新发送一次请求获取用户信息， 这样非常浪费性能
      // 解决方法：
      // 如果获取到了 userinfo 的数据, 就不要再发送请求了  ---  怎样才能知道请求成功了
      // 当我们请求成功后, 会将userInfo 中的数据存到 vuex 中
      // 此时可以进行一个判断，以 id 为例, vuex 里的数据 userInfo 有 id , 代表获取信息的请求已经发送过了, 否则就发送请求
      if (!store.state.user.userInfo.id) {
        const res = await store.dispatch('user/getUserInfoActions')
        // 通过 dispatch方法调用 actions 函数发送请求获取用户详细信息
        // 在 vuex 中对应的 actions 函数中通过 return 拿到返回值, 这里可以返回我们当前用户所拥有的所有权限, 页面权限与按钮权限
        // 利用 filter 与 includes 方法, 对动态路由表进行筛选, 遍历动态路由表, 如果当前项的子路由, 在用户权限列表包含有对应数据, 就筛出来
        const filterRoutes = asyncRoutes.filter(item => {
          const currentName = item.children[0].name
          return res.includes(currentName)
        })
        // 由于 * 路由会在用户输入的路由不存在时默认匹配到 * 路由, 如果将其放在静态路由中, 那么在后续 vuex 中进行动态路由与静态路由的拼接时
        // 就会出现无法正常跳转路由的问题
        // 解决方法: 将 * 路由添加在 筛选后的动态路由最后, 这样平解后, 匹配路由时最后才会匹配到 * 路由表
        filterRoutes.push({ path: '*', redirect: '/404', hidden: true })
        // 这里将筛选后的动态路由储存到 vuex 中进行共享的原因:
        // 由于使用 addRoutes 方法动态添加路由后, 虽然能够通过输入对应路由路径直接访问, 但是却不会在侧边栏显示
        // 因为 js 内的数据不具有响应式, 我们需要将动态添加路由后, 在vuex中将合并的路由共享起来
        // 这样无论是 js 文件还是组件内, 都能够访问
        // 最后, 我们可以在侧边栏组件内, 在 使用v-for循环渲染侧边栏子菜单时
        // 将原来直接从 router/index.js 文件读取路由表的方法替换为从 vuex 中读取动态添加的, 响应式的 路由表
        // 这样就能够实现实时的根据当前角色权限渲染侧边栏对应功能, 至此页面权限完整实现
        store.commit('menu/getAsyncRoutes', filterRoutes)
        // 将筛选后的路由表, 通过 addRoutes 方法, 动态的添加进路由对象内
        router.addRoutes(filterRoutes)
        next({
          ...to, //
          replace: true
        })
      } else {
        next()
      }
    }
  } else {
    // 没有登录过的逻辑 （用户通过一些地址栏，强行跳转到其他页面，我们应该有个拦截的操作）
    // 如果没有 token , 证明用户未登录, 那么就再次进行判断
    // 如果用户没登录, 并且要去的页面不是登录页, 就强制跳转到登录页
    // 如果用户没有登陆, 并且要去的是登录页, 就放行
    if (whiteList.includes(to.path)) {
      next()
    } else {
      next('/login')
      NProgress.done()
    }
  }
})

// 进入页面以后执行的钩子函数 afterEach
// afterEach 并不一定都会执行， 如果在进入的beforeEach钩子函数里面
// 通过next('参数') 跳转到了其他页面(将正常的跳转方向给他改变了)，这个afterEach就不会执行
router.afterEach(() => {
  NProgress.done()
})

// 请你描述一下路由守卫？
